//This file is a part of StoragePlug for Minecraft.
//http://code.google.com/p/minecraft-storageplug/
//StoragePlug is Copyright (C) 2011 Christopher Smith
//Released under the MIT license:
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights 
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//DEALINGS IN THE SOFTWARE.
//
//Related to Minecraft Copyright (C) 2009-2011 Mojang http://www.minecraft.net/

package net.minecraft.storageplug;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

public final class StreamStorageAdapter
	implements StorageProvider
{
	private StreamStorageProvider provider;
	
	public StreamStorageAdapter(StreamStorageProvider provider)
	{
		this.provider = provider;
	}
    
    private class ReadOperationAdatper
        implements StreamStorageProvider.ReadOperation
    {
        final Key key;
        DataTree dt;
        
        ReadOperationAdatper(Key key)
        {
            this.key = key;
        }

        @Override
        public void read(InputStream stream)
            throws Exception
        {
            dt = new DataTree(stream);
        }

        @Override
        public Key key()
        {
            return key;
        }
    }
    
    private class WriteOperationAdapter
        implements StreamStorageProvider.WriteOperation
    {
        final Key key;
        final DataTree dt;
        
        WriteOperationAdapter(Key key, DataTree dt)
        {
            this.key = key;
            this.dt = dt;
        }

        @Override
        public void write(OutputStream stream)
            throws Exception
        {
            dt.writeToStream(stream);
        }

        @Override
        public Key key()
        {
            return key;
        }        
    }
	
	@Override
	public DataTree readDataTree(Key key)
		throws Exception
	{
        ReadOperationAdatper op = new ReadOperationAdatper(key);
        provider.readDataStream(op);
        return op.dt;
	}

	@Override
	public void writeDataTree(DataTree dt, Key key)
		throws Exception
	{
		WriteOperationAdapter op = new WriteOperationAdapter(key, dt);
        provider.writeDataStream(op);
	}
	
    @Override
    public Collection<? extends Map.Entry<Key, DataTree>> readDataTreeBatch(Collection<? extends Key> list)
        throws Exception
    {
        ArrayList<ReadOperationAdatper> ops = new ArrayList<ReadOperationAdatper>(list.size());
        
        for(Key k : list)
            ops.add(new ReadOperationAdatper(k));
        
        provider.readDataStreamBatch(ops);
        
        ArrayList<SimpleEntry<Key, DataTree>> out = new ArrayList<SimpleEntry<Key, DataTree>>(list.size());
        
        for(ReadOperationAdatper op : ops)
            out.add(new SimpleEntry(op.key, op.dt));
        
        return out;
    }

    @Override
    public void writeDataTreeBatch(Collection<? extends Map.Entry<Key, DataTree>> list)
        throws Exception
    {
        ArrayList<WriteOperationAdapter> ops = new ArrayList<WriteOperationAdapter>(list.size());
        
        for(Map.Entry<Key, DataTree> e : list)
            ops.add(new WriteOperationAdapter(e.getKey(), e.getValue()));
        
        provider.writeDataStreamBatch(ops);
    }
	
	@Override
	public int nextUniqueID(String key)
		throws Exception
	{
		return provider.nextUniqueID(key);
	}

	@Override
	public void flush()
		throws Exception
	{
		provider.flush();		
	}

	@Override
	public void dispose()
		throws Exception
	{
		provider.dispose();
	}

	@Override
	public Collection<? extends Key> iterKeys(Class keytype)
		throws Exception
	{
		return provider.iterKeys(keytype);
	}

	@Override
	public Collection<? extends Map.Entry<String, Integer>> readUniqueIDs()
		throws Exception
	{
		return provider.readUniqueIDs();
	}

	@Override
	public void writeUniqueIDs(Collection<? extends Map.Entry<String, Integer>> map)
		throws Exception
	{
		provider.writeUniqueIDs(map);
	}
}
